﻿using System;
using System.ServiceModel;
using XchangeStreamer.Server;
using System.ServiceModel.Description;

namespace ConsoleStreamer
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            using (Streamer marketDataFeedService = new Streamer())
            {
                using (ServiceHost marketDataFeedServiceHost = new ServiceHost(marketDataFeedService, new System.Uri("http://localhost:6002/MarketDataFeedService"), new System.Uri("net.tcp://localhost:7002/MarketDataFeedService")))
                {
                    // NetTcp Binding
                    var netTcp = Init();

                    marketDataFeedServiceHost.AddServiceEndpoint("XchangeStreamer.Server.IPublisher", netTcp, "Publisher");
                    marketDataFeedServiceHost.AddServiceEndpoint("XchangeStreamer.Server.ISubscriber", netTcp, "Subscriber");

                    ServiceMetadataBehavior smb = marketDataFeedServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        smb = new ServiceMetadataBehavior();
                    }
                    smb.HttpGetEnabled = true;
                    marketDataFeedServiceHost.Description.Behaviors.Add(smb);

                    marketDataFeedServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

                    marketDataFeedServiceHost.Open();

                    Console.WriteLine("The market data feed service is available.");

                    Console.ReadKey(true);

                    marketDataFeedServiceHost.Close();
                    Console.WriteLine("The market data feed service is not available.");
                }
            }
        }

        private static NetTcpBinding Init()
        {
            // NetTcp Binding
            var netTcp = new NetTcpBinding(SecurityMode.None, true);

            netTcp.OpenTimeout = TimeSpan.FromDays(1);
            netTcp.CloseTimeout = TimeSpan.FromDays(1);
            netTcp.SendTimeout = TimeSpan.FromDays(1);
            netTcp.ReceiveTimeout = TimeSpan.FromDays(5);

            netTcp.Security.Mode = SecurityMode.None;
            netTcp.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
            netTcp.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;

            netTcp.ListenBacklog = int.MaxValue;
            netTcp.MaxBufferPoolSize = int.MaxValue;
            netTcp.MaxBufferSize = int.MaxValue;

            /*
             * (Not Supported on Mono)
             * 
            this.netTcp.MaxConnections = 1000;
            */

            netTcp.MaxReceivedMessageSize = int.MaxValue;
            netTcp.PortSharingEnabled = false;
            netTcp.TransferMode = TransferMode.Buffered;

            netTcp.ReaderQuotas.MaxArrayLength = int.MaxValue;
            netTcp.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
            netTcp.ReaderQuotas.MaxDepth = int.MaxValue;
            netTcp.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
            netTcp.ReaderQuotas.MaxStringContentLength = int.MaxValue;

            /*
             * (Not Supported on Mono)
             * 
            this.netTcp.ReliableSession.Enabled = true;
            this.netTcp.ReliableSession.InactivityTimeout = TimeSpan.FromDays(5);
            this.netTcp.ReliableSession.Ordered = true;
            */

            netTcp.ReliableSession.Enabled = false;
            netTcp.ReliableSession.InactivityTimeout = TimeSpan.FromDays(5);
            netTcp.ReliableSession.Ordered = true;

            return netTcp;
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine("Exception Message: {0}", e.ExceptionObject.ToString());
        }
    }
}

